package hikari.math;

import com.gooddies.wiring.Wiring;
import hikari.managers.Manager3D;
import org.swig.jirr.SColor;
import org.swig.jirr.vector3df;

/**
 * @author sad
 */
public class CircleDrawer {

    private vector3df center;
    private vector3df normal;
    private double radius;
    private vector3df[] vertex;
    private vector3df v1;
    private vector3df v2;
    private float zRotation = 0;
    Manager3D manager;
    public CircleDrawer(vector3df center, vector3df normal, double radius) {
        this(20, center, normal, radius, 0);
        manager=Wiring.getComponent(Manager3D.class);
    }

    public CircleDrawer(int vertexCount, vector3df center, vector3df normal, double radius) {
        this(vertexCount, center, normal, radius, 0);
        manager=Wiring.getComponent(Manager3D.class);
    }

    public CircleDrawer(int vertexCount, vector3df center, vector3df normal, double radius, float zRotation) {
        this.center = center;
        this.normal = normal;
        this.radius = radius;
        this.zRotation = (float) Math.toRadians(zRotation);
        if (vertexCount < 3) {
            vertexCount = 3;
        }
        normal.normalize();
        v1 = new vector3df(0, normal.getZ(), -normal.getY());
        v2 = new vector3df(normal.getZ(), 0, -normal.getX());
        if (!v1.equals(vector3df.NULLVECTOR)) {
            v1 = v1.dividedOperator((float) Math.sqrt(1 - (normal.getX() * normal.getX())));
            v2 = v1.crossProduct(normal);
        } else {
            v2 = v2.dividedOperator((float) Math.sqrt(1 - (normal.getY() * normal.getY())));
            v1 = v2.crossProduct(normal);
        }

        vertex = new vector3df[vertexCount];
        double dAngle = Math.PI / vertexCount * 2;
        for (int x = 0; x < vertexCount; x++) {
            vertex[x] = center.addOperator(v1.timesOperator((float) (radius * Math.cos((dAngle + zRotation) * x)))).addOperator(v2.timesOperator((float) (radius * Math.sin((dAngle + zRotation) * x))));
        }
    }

    public vector3df getPoint(float angle) {
        angle += zRotation;
        float radAngle = (float) Math.toRadians(angle);
        return center.addOperator(v1.timesOperator((float) (radius * Math.cos(radAngle)))).addOperator(v2.timesOperator((float) (radius * Math.sin(radAngle))));
    }

    public vector3df getPoint(int index) {
        return vertex[index];
    }

    public int getPointsCount() {
        return vertex.length;
    }

    public void drawCircle() {
        SColor color = new SColor(255, 255, 255, 255);
        for (int x = 0; x < vertex.length - 1; x++) {
            manager.getVideoDriver().draw3DLine(vertex[x], vertex[x + 1], color);
        }

        manager.getVideoDriver().draw3DLine(vertex[0], vertex[vertex.length - 1], color);
    }

    public void drawCircleFrontPart(vector3df cameraPosition) {
        SColor color = new SColor(255, 255, 255, 255);
        double lengthToCamera = cameraPosition.getDistanceFrom(center);
        for (int x = 0; x < vertex.length - 1; x++) {
            double l = cameraPosition.getDistanceFrom(vertex[x]);
            if (l < lengthToCamera) {
                manager.getVideoDriver().draw3DLine(vertex[x], vertex[x + 1], color);
            }
        }

        double l = cameraPosition.getDistanceFrom(vertex[0]);
        if (l < lengthToCamera) {
            manager.getVideoDriver().draw3DLine(vertex[0], vertex[vertex.length - 1], color);
        }
    }

    public void drawCircleNormal() {
        manager.getVideoDriver().draw3DLine(center, center.addOperator(normal.timesOperator(10)));
    }

    public vector3df getCenter() {
        return center;
    }

}
